/***************************************************************************************************

Code to replicate analyses in:

"Time to Degree in the Labor Market: Evidence from a Field Experiment"

By Michael D. Bloem

***************************************************************************************************/


*Edit global to the folder where the data is located
global project_folder ""


capture frame create full_dataset
frame change full_dataset

use "${project_folder}/public_dataset.dta", clear


*Globals for colors in figures
global blue "22 94 163"
global green "58 125 68"


*Program for plot of response & interview request rates by treatment group
capture program drop response_plot
program define response_plot

	syntax [if], min(real) max(real) color(string)

	frame change full_dataset
	reg PositiveResponse ttd6_ms ttd4_ls ttd6_ls `if', vce(cluster vacancy_id)
	global ttd4_ms = _b[_cons]
	frapply full_dataset, into(response_estimates, replace): regsave, ci
	frame change response_estimates
	replace coef = $ttd4_ms + coef if var!="_cons"
	replace ci_lower = $ttd4_ms + ci_lower if var!="_cons"
	replace ci_upper = $ttd4_ms + ci_upper if var!="_cons"
	gen order = 0.78 if var=="_cons"
	replace order = 1.78 if var=="ttd6_ms"
	replace order = 2.78 if var=="ttd4_ls"
	replace order = 3.78 if var=="ttd6_ls"
	gen outcome = "response"
	
	frame change full_dataset
	reg InterviewRequest ttd6_ms ttd4_ls ttd6_ls `if', vce(cluster vacancy_id)
	global ttd4_ms_int = _b[_cons]
	frapply full_dataset, into(interview_estimates, replace): regsave, ci
	frame change interview_estimates
	replace coef = $ttd4_ms_int + coef if var!="_cons"
	replace ci_lower = $ttd4_ms_int + ci_lower if var!="_cons"
	replace ci_upper = $ttd4_ms_int + ci_upper if var!="_cons"
	gen order = 1.22 if var=="_cons"
	replace order = 2.22 if var=="ttd6_ms"
	replace order = 3.22 if var=="ttd4_ls"
	replace order = 4.22 if var=="ttd6_ls"
	gen outcome = "interview"
	
	capture frame create estimates
	frame change estimates
	clear
	frappend response_estimates interview_estimates
	
	format coef %4.3f
	qui mylabels `min'(.05)`max', clean local(ylabels) format(%3.2f)
	local xlabels 1 `""4 years to degree;" "more selective""' 2 `""6 years to degree;" "more selective""' 3 `""4 years to degree;" "less selective""' 4 `""6 years to degree;" "less selective""'
	   
	twoway (bar coef order if outcome=="response", fcolor("`color'") lcolor(none) barwidth(.44)) ///
		   (bar coef order if outcome=="interview", fcolor("`color'") fintensity(50) lcolor(none) barwidth(.44)) ///
		   (rcap ci_lower ci_upper order, lcolor(black)) ///
		   (scatter coef order, msymbol(none) mlabel(coef) mlabsize(vsmall) mlabcolor(black) mlabposition(2)), ///
		   ytitle("") ylabel(`ylabels', angle(horizontal) format(%3.2f)) xlabel(`xlabels', labsize(small)) xtitle("") ///
		   legend(order(1 "Positive response" 2 "Interview request") region(lcolor(none)) position(11) ring(0) size(medsmall)) ///
		   plotregion(margin(sides))

	frame change full_dataset
end



/***************************************************************************************************
Table 2: Descriptive statistics by job characteristics
***************************************************************************************************/
frame change full_dataset

*Total
summ PositiveResponse InterviewRequest

*By city
forvalues i = 1/7 {
	summ PositiveResponse InterviewRequest if city==`i'
}

*By occupation
summ PositiveResponse InterviewRequest if occupation==1 | occupation==6
summ PositiveResponse InterviewRequest if occupation==2
summ PositiveResponse InterviewRequest if occupation==3
summ PositiveResponse InterviewRequest if occupation==4
summ PositiveResponse InterviewRequest if occupation==5
summ PositiveResponse InterviewRequest if occupation==9

*By above/below median salary
summ PositiveResponse InterviewRequest if higher_salary==1
summ PositiveResponse InterviewRequest if higher_salary==0

*By salary info source
summ PositiveResponse InterviewRequest if SalarySource=="Posted by employer"
summ PositiveResponse InterviewRequest if SalarySource=="Estimated by Indeed"
summ PositiveResponse InterviewRequest if SalarySource=="Scraped from Indeed"

*By job's number of hires
summ PositiveResponse InterviewRequest if Hires=="1"
summ PositiveResponse InterviewRequest if multiple_hires==1
summ PositiveResponse InterviewRequest if Hires==""

*Number of applicants
summ PositiveResponse InterviewRequest if Applicants_mid>28
summ PositiveResponse InterviewRequest if Applicants_mid<=28



/***************************************************************************************************
Table 3: Descriptive statistics by applicant characteristics
***************************************************************************************************/
frame change full_dataset

*Total
summ PositiveResponse InterviewRequest

*By gender and race
summ PositiveResponse InterviewRequest if white==1 & man==1
summ PositiveResponse InterviewRequest if white==1 & woman==1
summ PositiveResponse InterviewRequest if black==1 & man==1
summ PositiveResponse InterviewRequest if black==1 & woman==1

*Major
summ PositiveResponse InterviewRequest if major==1
summ PositiveResponse InterviewRequest if major==2
summ PositiveResponse InterviewRequest if major==3
summ PositiveResponse InterviewRequest if major==4
summ PositiveResponse InterviewRequest if major==5
summ PositiveResponse InterviewRequest if major==6
summ PositiveResponse InterviewRequest if major==7

*Degree type
summ PositiveResponse InterviewRequest if degree_label2==1
summ PositiveResponse InterviewRequest if degree_label2==2

*Order resume sent
summ PositiveResponse InterviewRequest if resume==1
summ PositiveResponse InterviewRequest if resume==2
summ PositiveResponse InterviewRequest if resume==3
summ PositiveResponse InterviewRequest if resume==4



/***************************************************************************************************
Figure 1: Employer response rates by resume treatment
***************************************************************************************************/
frame change full_dataset

response_plot, min(0) max(0.2) color("${blue}")



/***************************************************************************************************
Table 4: Full sample estimates
***************************************************************************************************/
frame change full_dataset

global controls "font format degree_label2 major work_template skill_template woman black resume city"

reg PositiveResponse ttd6 selective, vce(cluster vacancy_id)
reghdfe PositiveResponse ttd6 selective, vce(cluster vacancy_id) absorb(${controls})
reg PositiveResponse ttd6 selective 1.ttd6#1.selective, vce(cluster vacancy_id)
reghdfe PositiveResponse ttd6 selective 1.ttd6#1.selective, vce(cluster vacancy_id) absorb(${controls})

reg InterviewRequest ttd6 selective, vce(cluster vacancy_id)
reghdfe InterviewRequest ttd6 selective, vce(cluster vacancy_id) absorb(${controls})
reg InterviewRequest ttd6 selective 1.ttd6#1.selective, vce(cluster vacancy_id)
reghdfe InterviewRequest ttd6 selective 1.ttd6#1.selective, vce(cluster vacancy_id) absorb(${controls})



/***************************************************************************************************
Figure 2: Results by job quality
***************************************************************************************************/
frame change full_dataset

response_plot if higher_salary==1, min(0) max(0.25) color("$blue")

response_plot if higher_salary==0, min(0) max(0.25) color("$green")



/***************************************************************************************************
Table 5: Results by job opening characteristics
***************************************************************************************************/
frame change full_dataset

reg PositiveResponse ttd6 selective if higher_salary==1, vce(cluster vacancy_id)

reg PositiveResponse ttd6 selective if higher_salary==0, vce(cluster vacancy_id)

reg PositiveResponse ttd6 selective if Applicants_mid>=28 & !missing(Applicants_mid), vce(cluster vacancy_id)

reg PositiveResponse ttd6 selective if Applicants_mid<28 & !missing(Applicants_mid), vce(cluster vacancy_id)



/***************************************************************************************************
Figure 3: Results by number of applicants
***************************************************************************************************/
frame change full_dataset

response_plot if Applicants_mid>=28 & !missing(Applicants_mid), min(0) max(0.25) color("$blue")

response_plot if Applicants_mid<28 & !missing(Applicants_mid), min(0) max(0.25) color("$green")



/***************************************************************************************************
Figure 4: Employer response rates excluding jobs hiring multiple candidates
***************************************************************************************************/
frame change full_dataset

response_plot if multiple_hires==0, min(0) max(0.2) color("$blue")



/***************************************************************************************************
Table 6: Test of within-vacancy spillovers
***************************************************************************************************/
frame change full_dataset

*Column 3
reghdfe PositiveResponse ttd6 selective, vce(cluster vacancy_id) absorb(vacancy_id)
gen spillover_sample = (e(sample))

*Column 1
reg PositiveResponse ttd6 selective if spillover_sample==1, vce(cluster vacancy_id)

*Column 2
reg PositiveResponse ttd6 selective z_ttd6 z_selective if spillover_sample==1, vce(cluster vacancy_id)



/***************************************************************************************************
Appendix Figure A2: Results by gender of the applicant
***************************************************************************************************/
frame change full_dataset

response_plot if woman==0, min(0) max(0.25) color("$blue")

response_plot if woman==1, min(0) max(0.25) color("$green")



/***************************************************************************************************
Appendix Figure A3: Results by race of the applicant
***************************************************************************************************/
frame change full_dataset

response_plot if black==0, min(0) max(0.25) color("$blue")

response_plot if black==1, min(0) max(0.25) color("$green")



/***************************************************************************************************
Appendix Table A3: Balance tests – Resume characteristics
***************************************************************************************************/
frame change full_dataset

tab font, gen(font_)
tab format, gen(format_)
tab degree_label2, gen(degree_label2_)
tab major, gen(major_)
tab work_template, gen(work_template_)
tab skill_template, gen(skill_template_)

foreach var of varlist woman black degree_label2_* major_* work_template_* skill_template_* font_* format_* {
	
	tabstat `var', by(treat_group)
	reg `var' ttd6_ms ttd4_ls ttd6_ls
	
	test ttd6_ms = ttd4_ls = ttd6_ls
}



/***************************************************************************************************
Appendix Table A4: Balance tests – Assignment to job openings
***************************************************************************************************/
frame change full_dataset

tab resume, gen(order_)
tab city, gen(city_)
tab occupation, gen(occupation_)
tab dow_sent, gen(dow_sent_)
gen more_applicants = (Applicants_mid>=28) if !missing(Applicants_mid)


foreach var of varlist higher_salary more_applicants multiple_hires city_1 city_2 city_3 city_4 city_5 city_6 city_7 occupation_* order_* sent_morning sent_afternoon sent_evening sent_latenight dow_sent_* {
	
	tabstat `var', by(treat_group)
	reg `var' ttd6_ms ttd4_ls ttd6_ls
	
	test ttd6_ms = ttd4_ls = ttd6_ls
}



/***************************************************************************************************
Appendix Table A5: Full sample estimates, with coefficients on resume controls
***************************************************************************************************/
frame change full_dataset

reg PositiveResponse ttd6 selective 1.white#1.woman 1.black#1.man 1.black#1.woman i.major i.work_template i.skill_template, vce(cluster vacancy_id)

reg InterviewRequest ttd6 selective 1.white#1.woman 1.black#1.man 1.black#1.woman i.major i.work_template i.skill_template, vce(cluster vacancy_id)



/***************************************************************************************************
Appendix Table A6: Heterogeneity by applicant characteristics
***************************************************************************************************/
frame change full_dataset

reg PositiveResponse ttd6 selective if woman==0, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if woman==1, vce(cluster vacancy_id)

reg PositiveResponse ttd6 selective if black==0, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if black==1, vce(cluster vacancy_id)

reg InterviewRequest ttd6 selective if woman==0, vce(cluster vacancy_id)
reg InterviewRequest ttd6 selective if woman==1, vce(cluster vacancy_id)

reg InterviewRequest ttd6 selective if black==0, vce(cluster vacancy_id)
reg InterviewRequest ttd6 selective if black==1, vce(cluster vacancy_id)



/***************************************************************************************************
Appendix Table A7: Results by job opening characteristics - Interview request outcome
***************************************************************************************************/
frame change full_dataset

reg InterviewRequest ttd6 selective if higher_salary==1, vce(cluster vacancy_id)
reg InterviewRequest ttd6 selective if higher_salary==0, vce(cluster vacancy_id)

reg InterviewRequest ttd6 selective if Applicants_mid>=28 & !missing(Applicants_mid), vce(cluster vacancy_id)
reg InterviewRequest ttd6 selective if Applicants_mid<28 & !missing(Applicants_mid), vce(cluster vacancy_id)



/***************************************************************************************************
Appendix Table A8: Full sample estimates using a logit model
***************************************************************************************************/
frame change full_dataset

logit PositiveResponse ttd6 selective, vce(cluster vacancy_id)
margins, dydx(ttd6 selective)

logit PositiveResponse ttd6 selective i.font i.format i.degree_label2 i.major i.work_template i.skill_template woman black i.resume i.city, vce(cluster vacancy_id)
margins, dydx(ttd6 selective)

logit InterviewRequest ttd6 selective, vce(cluster vacancy_id)
margins, dydx(ttd6 selective)

logit InterviewRequest ttd6 selective i.font i.format i.degree_label2 i.major i.work_template i.skill_template woman black i.resume i.city, vce(cluster vacancy_id)
margins, dydx(ttd6 selective)



/***************************************************************************************************
Appendix Table A9: Results using alternative samples
***************************************************************************************************/
frame change full_dataset

reg PositiveResponse ttd6 selective if occupation!=1, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if occupation!=2, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if occupation!=3, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if occupation!=4, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if occupation!=5, vce(cluster vacancy_id)
reg PositiveResponse ttd6 selective if occupation!=6, vce(cluster vacancy_id)

